#include "myview.h"

#include "boxgroup.h"

#include <OneBox.h>
#include <QAudioOutput>
#include <QDebug>
#include <QGraphicsEffect>
#include <QGraphicsWidget>
#include <QKeyEvent>
#include <QLabel>
#include <QMessageBox>
#include <QPalette>
#include <QPushButton>

static QString SOUNDSPATH = "./sounds";

MyView::MyView(QWidget *parent)
    : QGraphicsView(parent)
{
    initView();
}

MyView::~MyView()
{
}

void MyView::updateScoreAndLevel(int num)
{
    score = num;
    label->setText(tr("当前得分: %1").arg(score));
    if(score <= 100) return;
    else if(score <= 300){
        if(level == 2) return;
        curBoxGroup->endTimer(); //暂停下落

        // 设置场景
        QGraphicsScene *scene = this->scene();
        scene->setBackgroundBrush(QPixmap(":/images/background01.png"));
        scene->update();

        //难度显示
        level = 2;
        levelText->setHtml(tr("<font color = white>第<br>二<br>幕</font>"));
        backgroundPlayer->setSource(QUrl::fromLocalFile(SOUNDSPATH+"/background01.mp3"));

        //设置速度更新
        gameSpeed = 500;
        curBoxGroup->startTimer(gameSpeed);
    }else{
        if(level == 3) return;
        curBoxGroup->endTimer(); //暂停下落

        // 设置场景
        QGraphicsScene *scene = this->scene();
        scene->setBackgroundBrush(QPixmap(":/images/background02.png"));
        scene->update();

        //难度显示
        level = 3;
        levelText->setHtml(tr("<font color = white>第<br>三<br>幕</font>"));
        backgroundPlayer->setSource(QUrl::fromLocalFile(SOUNDSPATH+"/background02.mp3"));

        //设置速度更新
        gameSpeed = 250;
        curBoxGroup->startTimer(gameSpeed);
    }
}

void MyView::enterGame()
{
    hideMainMenu();
}

void MyView::startGame()
{
    // 设置场景，并清除绘图区
    QGraphicsScene *scene = this->scene();
    clearBox();
    //难度显示
    level = 1;
    levelText->setHtml(tr("<font color = white>第<br>一<br>幕</font>"));
    //创建一个nextBoxGroup
    curBoxGroup = NULL;
    nextBoxGroup = new BoxGroup();
    scene->addItem(nextBoxGroup);
    createBoxGroup();
    updateScoreAndLevel(0);
    setFocus();
    gameFlag = true;
}

void MyView::restartGame()
{
    startGame();
}

void MyView::endGame()
{
    // 设置场景
    QGraphicsScene *scene = this->scene();
    clearBox();
    setFocus();
    updateScoreAndLevel(0);
    gameFlag = false;
}

void MyView::pauseGame()
{
    gameFlag = false;
    setFocus();
    if(!curBoxGroup) return;
    curBoxGroup->setGameFlag(gameFlag);
    showPauseWidget();
}

void MyView::returnGame()
{
    gameFlag = true;
    setFocus();
    if(!curBoxGroup) return;
    curBoxGroup->setGameFlag(gameFlag);
    hidePauseWidget();
}

void MyView::exitGame()
{
    close();
}

void MyView::showMainMenu()
{
    if(gameFlag){
        pauseGame();
        int result = QMessageBox::question(this, "提醒", "是否结束本局游戏，返回主菜单？", QMessageBox::Yes, QMessageBox::No);
        if(result != QMessageBox::Yes){
            returnGame();
            return;
        }
        hidePauseWidget();
    }
    clearBox();
    scene()->setBackgroundBrush(QPixmap(":/images/background.png"));
    backgroundPlayer->setSource(QUrl::fromLocalFile(SOUNDSPATH+"/background.mp3"));
    maskWidget->show();
    welcomeText->show();
    enterBtn->show();
    exitBtn->show();

    startBtn->hide();
    restartBtn->hide();
    pauseBtn->hide();
    mainMenuBtn->hide();
    label->hide();
    levelText->hide();
    topLine->hide();
    bottomLine->hide();
    leftLine->hide();
    rightLine->hide();
}

void MyView::hideMainMenu()
{
    maskWidget->hide();
    welcomeText->hide();
    enterBtn->hide();
    exitBtn->hide();

    startBtn->show();
    restartBtn->show();
    pauseBtn->show();
    mainMenuBtn->show();
    label->show();
    topLine->show();
    bottomLine->show();
    leftLine->show();
    rightLine->show();
}

void MyView::showPauseWidget()
{
    returnBtn->show();
    maskWidget->show();
    pauseText->show();
    backgroundVolumnText->show();
    clearFullLineVolumnText->show();
    backgroundVolumnSliderProxy->show();
    clearFullLineVolumnSliderProxy->show();

    startBtn->hide();
    restartBtn->hide();
    pauseBtn->hide();
    mainMenuBtn->hide();
}

void MyView::hidePauseWidget()
{
    returnBtn->hide();
    maskWidget->hide();
    pauseText->hide();
    backgroundVolumnText->hide();
    clearFullLineVolumnText->hide();
    backgroundVolumnSliderProxy->hide();
    clearFullLineVolumnSliderProxy->hide();

    startBtn->show();
    restartBtn->show();
    pauseBtn->show();
    mainMenuBtn->show();
}

void MyView::playMedia(QMediaPlayer::MediaStatus status)
{
    if(status == QMediaPlayer::LoadedMedia) backgroundPlayer->play();
}

void MyView::setBackGroundVolumn(float num)
{
    backgroundAudio->setVolume(num / 100.0);
}

void MyView::setClearFullLineVolumn(float num)
{
    clearFullLineAudio->setVolume(num / 100.0);
}



void MyView::keyPressEvent(QKeyEvent *event)
{
    if(!gameFlag || !curBoxGroup) return;
    qDebug() << "Press Button: "<< event->key();
    curBoxGroup->keyPressEvent(event);
}

void MyView::initView()
{

    // 使用抗锯齿渲染
    setRenderHint(QPainter::Antialiasing);
    // 设置缓存背景，这样可以加快渲染速度
    setCacheMode(CacheBackground);
    setWindowTitle(tr("MyBox方块游戏"));
    setWindowIcon(QIcon(":/images/icon.png"));
    setMinimumSize(810, 510);
    setMaximumSize(810, 510);

    // 设置场景
    QGraphicsScene *scene = new QGraphicsScene;
    scene->setSceneRect(5, 5, 800, 500);
    scene->setBackgroundBrush(QPixmap(":/images/background.png"));
    setScene(scene);

    // 方块可移动区域的四条边界线
    topLine = scene->addLine(197, 47, 403, 47);
    bottomLine = scene->addLine(197,453,403,453);
    leftLine = scene->addLine(197,47,197,453);
    rightLine = scene->addLine(403,47,403,453);
    topLine->hide();
    bottomLine->hide();
    leftLine->hide();
    rightLine->hide();

    //背景音乐设置
    backgroundPlayer = new QMediaPlayer(this);
    backgroundAudio = new QAudioOutput;
    backgroundPlayer->setAudioOutput(backgroundAudio);
    backgroundPlayer->setSource(QUrl::fromLocalFile(SOUNDSPATH+"/background.mp3"));
    backgroundPlayer->setLoops(QMediaPlayer::Infinite);
    connect(backgroundPlayer, &QMediaPlayer::mediaStatusChanged, this, &MyView::playMedia);

    //消除音乐设置
    clearFullLinePlayer = new QMediaPlayer(this);
    clearFullLineAudio = new QAudioOutput;
    clearFullLinePlayer->setAudioOutput(clearFullLineAudio);
    clearFullLinePlayer->setSource(QUrl::fromLocalFile(SOUNDSPATH+"/clearRow.mp3"));

    //开始游戏按钮
    QPushButton *startBtnWidget = new QPushButton("开始游戏");
    connect(startBtnWidget, &QPushButton::clicked, this, &MyView::startGame);
    startBtn = scene->addWidget(startBtnWidget);
    startBtn->setGeometry(QRectF(600, 100, 60, 30));
    startBtn->hide();

    //重新开始游戏按钮
    QPushButton *restartBtnWidget = new QPushButton("重新开始");
    connect(restartBtnWidget, &QPushButton::clicked, this, &MyView::restartGame);
    restartBtn = scene->addWidget(restartBtnWidget);
    restartBtn->setGeometry(QRectF(600, 150, 60, 30));
    restartBtn->hide();

    //暂停游戏按钮
    QPushButton *pauseBtnWidget = new QPushButton("暂停游戏");
    connect(pauseBtnWidget, &QPushButton::clicked, this, &MyView::pauseGame);
    pauseBtn = scene->addWidget(pauseBtnWidget);
    pauseBtn->setGeometry(QRectF(600, 200, 60, 30));
    pauseBtn->hide();

    //返回游戏按钮
    QPushButton *returnBtnWidget = new QPushButton("返回游戏");
    connect(returnBtnWidget, &QPushButton::clicked, this, &MyView::returnGame);
    returnBtn = scene->addWidget(returnBtnWidget);
    returnBtn->setGeometry(QRectF(350, 180, 60, 30));
    returnBtn->setZValue(2);
    returnBtn->hide();

    //主菜单进入游戏按钮
    QPushButton *enterBtnWidget = new QPushButton("进入游戏");
    connect(enterBtnWidget, &QPushButton::clicked, this, &MyView::enterGame);
    enterBtn = scene->addWidget(enterBtnWidget);
    enterBtn->setGeometry(QRectF(350, 180, 60, 30));
    enterBtn->setZValue(2);

    //退出游戏按钮
    QPushButton *exitBtnWidget = new QPushButton("退出游戏");
    connect(exitBtnWidget, &QPushButton::clicked, this, &MyView::exitGame);
    exitBtn = scene->addWidget(exitBtnWidget);
    exitBtn->setGeometry(QRectF(350, 240, 60, 30));
    exitBtn->setZValue(2);

    //音量条
    backgroundVolumnSlider = new QSlider(Qt::Horizontal);
    backgroundVolumnSliderProxy = scene->addWidget(backgroundVolumnSlider);
    backgroundVolumnSliderProxy->setGeometry(QRectF(350, 250,100,30));
    backgroundVolumnSliderProxy->setZValue(2);
    connect(backgroundVolumnSlider, &QSlider::valueChanged, this, &MyView::setBackGroundVolumn);
    backgroundVolumnSlider->setValue(50);
    backgroundVolumnSlider->setStyleSheet("QSlider{background-color:rgba(255, 255, 224, 0%);}");
    backgroundVolumnSliderProxy->hide();

    clearFullLineVolumnSlider = new QSlider(Qt::Horizontal);
    clearFullLineVolumnSliderProxy = scene->addWidget(clearFullLineVolumnSlider);
    clearFullLineVolumnSliderProxy->setGeometry(QRectF(350, 320, 100,30));
    clearFullLineVolumnSliderProxy->setZValue(2);
    connect(clearFullLineVolumnSlider, &QSlider::valueChanged, this, &MyView::setClearFullLineVolumn);
    clearFullLineVolumnSlider->setValue(30);
    clearFullLineVolumnSlider->setStyleSheet("QSlider{background-color:rgba(255, 255, 224, 0%);}");
    clearFullLineVolumnSliderProxy->hide();

    //音量提示text
    backgroundVolumnText = new QGraphicsTextItem;
    scene->addItem(backgroundVolumnText);
    backgroundVolumnText->setPlainText("背景音量");
    backgroundVolumnText->setDefaultTextColor(Qt::red);
    backgroundVolumnText->setFont(QFont("Times", 18, QFont::Bold));
    backgroundVolumnText->setPos(240, 250);
    backgroundVolumnText->setZValue(2);
    backgroundVolumnText->hide();
    clearFullLineVolumnText = new QGraphicsTextItem;
    scene->addItem(clearFullLineVolumnText);
    clearFullLineVolumnText->setPlainText("消除音量");
    clearFullLineVolumnText->setFont(QFont("Times", 18, QFont::Bold));
    clearFullLineVolumnText->setDefaultTextColor(Qt::red);
    clearFullLineVolumnText->setPos(240, 320);
    clearFullLineVolumnText->setZValue(2);
    clearFullLineVolumnText->hide();


    //主菜单按钮
    QPushButton *mainMenuBtnWidget = new QPushButton("主菜单");
    connect(mainMenuBtnWidget, &QPushButton::clicked, this, &MyView::showMainMenu);
    mainMenuBtn = scene->addWidget(mainMenuBtnWidget);
    mainMenuBtn->setGeometry(QRectF(600, 250, 60, 30));
    mainMenuBtn->hide();

    //遮罩页面
    maskWidget = scene->addWidget(new QWidget);
    maskWidget->setAutoFillBackground(true);
    maskWidget->setPalette(QPalette(QColor(0, 0, 0, 80)));
    maskWidget->resize(900, 600);
    maskWidget->setPos(-50, -50);
    // 设置其Z值为1，这样可以处于Z值为0的图形项上面
    maskWidget->setZValue(1);

    // 游戏欢迎文本
    welcomeText = new QGraphicsTextItem;
    scene->addItem(welcomeText);
    welcomeText->setHtml(tr("<font color=white>MyBox方块游戏</font>"));
    welcomeText->setFont(QFont("Times", 30, QFont::Bold));
    welcomeText->setPos(250, 100);
    welcomeText->setZValue(2);

    // 游戏暂停文本
    pauseText = new QGraphicsTextItem;
    scene->addItem(pauseText);
    pauseText->setHtml(tr("<font color=white>游戏暂停中！</font>"));
    pauseText->setFont(QFont("Times", 30, QFont::Bold));
    pauseText->setPos(300, 100);
    pauseText->setZValue(2);
    pauseText->hide();

    //积分显示
    score = 0;
    label = new QLabel(tr("当前得分: %1").arg(score));
    scene->addWidget(label);
    label->setGeometry(600, 300, 100, 50);
    label->setAlignment(Qt::AlignCenter);
    label->setStyleSheet("QLabel{background-color:rgba(255, 255, 224, 50%);}");
    label->hide();

    //难度显示
    levelText = new QGraphicsTextItem;
    scene->addItem(levelText);
    levelText->setPos(100, 150);
    levelText->setFont(QFont("Times", 30, QFont::Bold));
}

void MyView::createBoxGroup(){
    // 设置场景
    QGraphicsScene *scene = this->scene();
    //先清理，再创建
    cleanFullLine();
    if(checkEnd()){
        int result = QMessageBox::question(this, "游戏结束", tr("本局游戏得分为: %1, 是否重新开始下一局").arg(score), QMessageBox::Yes, QMessageBox::No);
        if(result == QMessageBox::Yes){
            startGame();
            return;
        }else{
            endGame();
            return;
        }
    }
    curBoxGroup = nextBoxGroup;
    curBoxGroup->moveToScreen();
    connect(curBoxGroup, &BoxGroup::needNewBox, this, &MyView::createBoxGroup);
    curBoxGroup->startTimer(gameSpeed);
    nextBoxGroup = new BoxGroup();
    scene->addItem(nextBoxGroup);
}

void MyView::cleanFullLine()
{
    QRectF beginScanRect(200, 430.5, 200, 19);
    QGraphicsScene *scene = this->scene();
    QList<QGraphicsItem *> *removeList = new QList<QGraphicsItem *>();
    int num = 0;
    while(beginScanRect.y() >= 50.5 && scene->items(beginScanRect).count() != 0){
        qDebug() << "当前扫描行: "<<beginScanRect <<"扫描item数: "<<scene->items(beginScanRect).count();
        if(scene->items(beginScanRect).count() == 10){
            //记录本行，并下移其他所有item
            removeList->append(scene->items(beginScanRect));
            updateScoreAndLevel(score + 10);
            num += 20;
        }else{
            //将当前行下落num高度
            foreach (QGraphicsItem *item, scene->items(beginScanRect)) {
                item->moveBy(0, num);
            }
        }
        //扫描行上移
        beginScanRect.moveTop(beginScanRect.y()-20);
    }
    foreach (QGraphicsItem *item, *removeList) {
        QGraphicsEffect *blurEffect = new QGraphicsBlurEffect;
        item->setGraphicsEffect(blurEffect);
        QPropertyAnimation *anim = new QPropertyAnimation;
        anim->setPropertyName("scale");
        anim->setTargetObject(static_cast<QGraphicsObject *>(item));
        anim->setDuration(250);
        anim->setStartValue(4);
        anim->setEndValue(0.25);
        anim->setEasingCurve(QEasingCurve::OutBounce);
        anim->start(QPropertyAnimation::DeleteWhenStopped);
        connect(anim, &QPropertyAnimation::finished, static_cast<QGraphicsObject *>(item), &QGraphicsObject::deleteLater);
    }
    if(removeList->count() > 0) clearFullLinePlayer->play();
    removeList->clear();
}

bool MyView::checkEnd()
{
    //检查最后一行是否有方块
    QRectF endScanRect(200, 50.5, 200, 19);
    QGraphicsScene *scene = this->scene();
    if(scene->items(endScanRect).count() > 0) return true;
    return false;
}

void MyView::clearBox()
{
    QGraphicsScene *scene = this->scene();
    qDebug() << "清理区域items数" << scene->items(QRectF(200, 50, 200, 400)).count();
    //清除boxgroup
    if(curBoxGroup){
        curBoxGroup->clearBox();
        curBoxGroup->hide();
    }
    if(nextBoxGroup){
        nextBoxGroup->clearBox();
        nextBoxGroup->hide();
    }
    //清除box
    foreach (QGraphicsItem *item, scene->items(QRectF(200, 50, 200, 400))) {
        scene->removeItem(item);
        static_cast<OneBox *>(item)->deleteLater();
    }
    curBoxGroup = NULL;
    nextBoxGroup = NULL;
}






